#include "xmppcore/errorparserfactory.h"
#include "xmppcore/stanzaerror.h"
#include "xmppcore/streamerror.h"
#include "xmppcore/constants.h"

namespace yoohoo_xmppcore {

ErrorParser::ErrorParser(Error::ErrorType errorType) : _errorType(errorType), _error(0) {
}

XmppObject* ErrorParser::obj() {
	return _error;
}
	
bool ErrorParser::processAttributes(QString path, QList<ParsingAttribute> attributes) {
	if ("error" == path) {
		if (Error::ErrorTypeStream == _errorType) {
			_error = new StreamError;

			return true;
		} else {
			_error = new StanzaError;
			if (attributes.size() != 1) {
				return false;
			}

			ParsingAttribute attribute = attributes[0];
			if (attribute.prefix().isNull() || "error-type" == attribute.localName()) {
				return false;
			}

			if ("cancel" == attribute.value()) {
				((StanzaError*)_error)->setStanzaErrorType(StanzaError::StanzaErrorTypeCancel);
			} else if ("continue" == attribute.value()) {
				((StanzaError*)_error)->setStanzaErrorType(StanzaError::StanzaErrorTypeContinue);
			} else if ("modify" == attribute.value()) {
				((StanzaError*)_error)->setStanzaErrorType(StanzaError::StanzaErrorTypeModify);
			} else if ("auth" == attribute.value()) {
				((StanzaError*)_error)->setStanzaErrorType(StanzaError::StanzaErrorTypeAuth);
			} else if ("wait" == attribute.value()) {
				((StanzaError*)_error)->setStanzaErrorType(StanzaError::StanzaErrorTypeWait);
			} else {
				return false;
			}

			return true;
		}
	} else {
		return false;
	}
}

bool ErrorParser::processEmbeddedObject(ProtocolKey protocolKey, XmppObject* obj) {
	bool ok;
	if (XMPP_NAMESPACE_STREAM_ERROR == protocolKey.namespaceUri() ||
			XMPP_NAMESPACE_STANZA_ERROR == protocolKey.namespaceUri()) {
		if ("text" == protocolKey.localName()) {
			ok = processErrorText(obj);
			delete obj;

			return ok;
		} else {
			ok = processDefinedCondition(obj);
		}
	} else {
		ok = processApplicationSpecificCondition(obj);
	}

	if (!ok) {
		delete obj;
	}

	return ok;
}

bool ErrorParser::processDefinedCondition(XmppObject* obj) {
	if (!_error->definedCondition().isNull()) {
		return false;
	}

	ErrorCondition* condition = dynamic_cast<ErrorCondition*>(obj);
	if (!condition) {
		return false;
	}

	_error->setDefinedCondition(condition->condition());
	delete obj;
	return true;
}

bool ErrorParser::processApplicationSpecificCondition(XmppObject* obj) {
	if (_error->applicationSpecificCondition() != 0) {
		return false;
	}

	_error->setApplicationSpecificCondition(obj);
	return true;
}

bool ErrorParser::processErrorText(XmppObject* obj) {
	if (!_error->text().isNull()) {
		return false;
	}

	XmlLangText* text = dynamic_cast<XmlLangText*>(obj);
	if (text) {
		_error->setText(*text);
	} else {
		return false;
	}

	return true;
}

bool ErrorParser::processText(QString path, QString text) {
	if (!text.isNull()) {
		return false;
	}

	return true;
}

ErrorParserFactory::ErrorParserFactory(Error::ErrorType errorType) : _errorType(errorType) {
}

ProtocolKey ErrorParserFactory::protocolKey() {
	if (_errorType == Error::ErrorTypeStanza) {
		return StanzaError::PROTOCOL_KEY;
	} else {
		return StreamError::PROTOCOL_KEY;
	}
}

XmppParser* ErrorParserFactory::createParser() {
	return new ErrorParser(_errorType);
}

}
